#pragma once

#include <iostream>
#include <string>
#include <vector>
#include "Mutex.hpp"
#include "Cond.hpp"
#include "InetAddr.hpp"
#include "Log.hpp"

using namespace LogModule;
using namespace MutexModule;

class Route
{
private:
    bool IsExit(InetAddr &peer)
    {
        for (auto &user : _online_user)
        {
            if (user == peer)
            {
                return true;
            }
        }

        return false;
    }

    void AddUser(InetAddr &peer)
    {
        LOG(LogLevel::INFO) << "新增一个用户在线用户： " << peer.StringAddr();
        _online_user.push_back(peer);
    }

    void DeleteUser(InetAddr &peer)
    {
        for (auto iter = _online_user.begin(); iter != _online_user.end(); iter++)
        {
            if (*iter == peer)
            {
                _online_user.erase(iter);
                LOG(LogLevel::INFO) << "有一个在线用户离线：" << peer.StringAddr() << "  离线成功";
                break;
            }
        }
    }

public:
    Route()
    {
    }

    // 要发送路由，首先要获取发送方的套接字，发送的信息，以及发送方的信息
    void RouteMessage(int sockfd, const std::string &message, InetAddr &peer)
    {
        LOG(LogLevel::DEBUG) << "进入了路由！"; // 可以！

        {
            LockGuard lockguard(_mutex);

            if (!IsExit(peer))
            {
                AddUser(peer);
            }

            std::string send_message = peer.StringAddr() + "# " + message;

            // 给每个在线的用户都发送消息  泛洪
            for (auto &user : _online_user)
            {
                sendto(sockfd, send_message.c_str(), send_message.size(), 0, (struct sockaddr *)&user.NetAddr(), sizeof(user.NetAddr()));
            }

            // 如果输入的是QUIT，先打印，后执行离线状态
            if (message == "QUIT")
            {
                LOG(LogLevel::INFO) << "有一个在线用户离线：" << peer.StringAddr();
                DeleteUser(peer);
            }
        }
    }

    ~Route() {}

private:
    // 将首次发送消息的客户端标记为在线用户
    std::vector<InetAddr> _online_user; // 临界资源
    Mutex _mutex;
};